package lzm.register;

import lzm.factory.ServiceFactory;
import lzm.spring.config.EnableRpcPost;
import lzm.spring.rpc.RpcClient;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;

import java.beans.Introspector;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;


public class BeanRegister02 implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {

    private ResourceLoader resourceLoader;
    private Environment environment;


    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        Map<String, Object> attrs = importingClassMetadata.getAnnotationAttributes(EnableRpcPost.class.getName());
        for (Object value : attrs.values()) {
            String packageName = String.valueOf(value);

            URL resource = this.getClass().getClassLoader().getResource(packageName.replace(".", "/"));
            File file = new File(resource.getFile());
            Set<Class> classes = this.getClass(file, packageName);
            for (Class aClass : classes) {
                AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
                beanDefinition.setBeanClass(ServiceFactory.class);
                beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(aClass);
                //重点
                registry.registerBeanDefinition(Introspector.decapitalize(aClass.getSimpleName()), beanDefinition);
            }
        }
    }


    private Set<Class> getClass(File file, String packageName) {
        if(file.isDirectory()) {
            File[] files = file.listFiles();
            return Arrays.stream(files).map(line -> getClass(line, packageName))
                    .flatMap(Collection::stream)
                    .collect(Collectors.toSet());
        } else {
            String fileName = file.getAbsolutePath();
            fileName = fileName.replace(".class", "").replace("\\", ".");
            String className = fileName.substring(fileName.indexOf(packageName));
            Class<?> clazz = null;
            try {
                clazz = this.getClass().getClassLoader().loadClass(className);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            Set<Class> set = new HashSet<>();
            set.add(clazz);
            return set;
        }
    }





    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

}